<script setup lang="ts">
import dayjs from 'dayjs'
import { cloneDeep, debounce } from 'lodash-es'

import type { DatePickerProps } from 'element-plus'
import StatisticsBar from '../StatisticsBar/StatisticsBar.vue'
import StatisticsTabs from '../StatisticsTabs/index.vue'
import StatisticsTable from '../StatisticsTable/StatisticsTable.vue'

import type {
  Query,
  StatisticsBarProps,
  StatisticsTableProps,
  StatisticsTabsProps,
} from '../type'
import type { ViewChartPieProps } from '@/components/view-chart-pie/type'
import type { Point } from '@/components/ReadonlyPointTree/ReadonlyPointTree'
import { CHART_SYMBOL } from '@/symbol'
import { useChartToolboxDataView } from '@/mixins/MixinChartToolboxDataView'

const props = withDefaults(
  defineProps<{
    /** 能源类型卡片组件Props */
    tabsProps?: StatisticsTabsProps
    /** 堆叠图组件Props */
    barProps?: StatisticsBarProps
    /** 饼图组件Dataset */
    pieProps?: ViewChartPieProps['dataset']
    /** 表格组件Props */
    tableProps?: StatisticsTableProps
    /** 是否显示用能单元树，默认 true */
    showPointTree?: boolean
    loading?: boolean
    /** 图表高度，默认 300 */
    chartHeight?: number
    showTips?: boolean
    /** 空饼图 */
    emptyPie?: boolean
    dataViewFirstCellName?: string
  }>(),
  {
    showPointTree: true,
    loading: false,
    chartHeight: 230,
    tabsProps() {
      return {
        data: [],
      }
    },
    barProps() {
      return {
        x: [],
        y: [],
        l: [],
      }
    },
    tableProps() {
      return {
        columns: [],
        data: [],
      }
    },
    pieProps() {
      return {
        dimensions: [],
        source: [],
      }
    },
    showTips: true,
  },
)

const emits = defineEmits<{
  (e: 'query-change', value: Query): void
  (e: 'energy-change', value: Query): void
}>()

/** 统计类型 */
enum STATISTICS_TYPES {
  /** 年 */
  YEAR = 3,
  /** 月 */
  MONTH = 2,
  /** 日 */
  DAY = 1,
}

type PickerType = DatePickerProps['type']
const autoResizeEnabled = inject<
  null | ((callback?: () => void) => void)
    >(CHART_SYMBOL.RESIZE_ENABLE)
const resizeTrigger = inject<null | (() => void)>(
  CHART_SYMBOL.RESIZE_TRIGGER,
)
const options = [
  {
    label: '日',
    value: STATISTICS_TYPES.DAY,
  },
  {
    label: '月',
    value: STATISTICS_TYPES.MONTH,
  },
  {
    label: '年',
    value: STATISTICS_TYPES.YEAR,
  },
]
const [hideTrend, setHideTrend] = useState(false)
const query: Query = reactive({
  type: STATISTICS_TYPES.DAY,
  /** 默认统计昨天 */
  time: dayjs().subtract(1, 'day').format('YYYY-MM-DD'),
  pointId: undefined,
  energyType: undefined,
})

const pickerType = computed<PickerType>(() => {
  const type = query.type
  switch (type) {
    case STATISTICS_TYPES.DAY:
      return 'date'
    case STATISTICS_TYPES.MONTH:
      return 'month'
    case STATISTICS_TYPES.YEAR:
      return 'year'
  }
  return 'date'
})
const pickerFormatter = computed(() => {
  const type = query.type
  switch (type) {
    case STATISTICS_TYPES.DAY:
      return 'YYYY-MM-DD'
    case STATISTICS_TYPES.MONTH:
      return 'YYYY-MM'
    case STATISTICS_TYPES.YEAR:
      return 'YYYY'
  }
  return 'YYYY-MM-DD'
})

const allEmpty = computed(() => {
  return props.tabsProps.data.length === 0 && false
})
const chartStyle = computed(() => {
  return unref(allEmpty)
    ? {
        width: '300px',
        height: '200px',
      }
    : {
        height: `${props.chartHeight}px`,
      }
})

const container = ref<HTMLElement | null>(null)

const debounceFn = debounce(
  (
    event: 'query-change' | 'energy-change',
    params: Query,
  ) => {
    if (props.loading)
      return
    if (event === 'query-change') {
      emits('query-change', params)
    }
    else if (event === 'energy-change') {
      emits('energy-change', params)
    }
  },
  300,
)

const { dataView } = useChartToolboxDataView(() => ({
  dataViewFirstCellName: props.dataViewFirstCellName ?? '名称',
  optionToContent: (opt, g: (d: any[]) => string | HTMLElement) => {
    let result = cloneDeep(opt.dataset[0]?.source || [])
    // console.log(result)
    const head = result[0]
    const rest = result.splice(1)
    // DESC
    if (result.length > 0) {
      rest.sort((a: any, b: any) => {
        return b[1] - a[1]
      })
      result = [
        head,
        ...rest,
      ]
    }
    return g(result)
  },
}))

function disabledDate(date: Date) {
  return date.getTime() > Date.now()
}

function resetTimeOnTypeChange(val: STATISTICS_TYPES) {
  switch (val) {
    case STATISTICS_TYPES.DAY:
      query.time = dayjs()
        .subtract(1, 'day')
        .format('YYYY-MM-DD')
      break
    case STATISTICS_TYPES.MONTH:
      query.time = dayjs()
        .subtract(1, 'month')
        .format('YYYY-MM')
      break
    case STATISTICS_TYPES.YEAR:
      query.time = dayjs()
        .subtract(1, 'year')
        .format('YYYY')
      break
  }
}

function changeTypeHandler() {
  resetTimeOnTypeChange(query.type)
}
function clickNodeHandler(o: Point) {
  query.pointId = o.id
  setHideTrend(query.type === STATISTICS_TYPES.YEAR)
  debounceFn('query-change', query)
}
function clickTabHandler() {
  debounceFn('energy-change', query)
}
function handleClick() {
  setHideTrend(query.type === STATISTICS_TYPES.YEAR)
  emits('query-change', query)
}
watch(
  () => allEmpty.value,
  () => {
    resizeTrigger?.()
  },
)

onMounted(() => {
  autoResizeEnabled?.()
})

defineExpose({ query })
</script>

<template>
  <div
    ref="container"
    v-loading="loading"
    element-loading-custom-class="global-loading"
    class="padding-sm flex container"
  >
    <div v-if="showPointTree" class="flex-shrink-0">
      <ReadonlyPointTree
        fire
        @click-node="clickNodeHandler"
      />
    </div>
    <div
      class="flex-fillRemaining flex-direction flex overflow-auto"
      :class="{
        'margin-left-sm': showPointTree,
      }"
    >
      <div class="flex-shrink-0">
        <ElForm inline>
          <ElFormItem label="统计类型">
            <ElSelect
              v-model="query.type"
              class="type-select free"
              @change="changeTypeHandler"
            >
              <ElOption
                v-for="item in options"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </ElSelect>
            <ElDatePicker
              v-model="query.time"
              class="time-picker"
              :type="pickerType"
              :format="pickerFormatter"
              :value-format="pickerFormatter"
              :clearable="false"
              :disabled-date="disabledDate"
            />
          </ElFormItem>
          <ElFormItem>
            <SearchButton
              @click="handleClick"
            />
          </ElFormItem>
        </ElForm>
      </div>
      <div v-show="allEmpty" class="energy-empty">
        <TableEmpty text="暂无能源数据" />
      </div>
      <div
        v-show="!allEmpty"
        class="flex-fillRemaining flex-direction statistics-main-wrapper flex overflow-hidden"
        :class="{ 'is-all-empty': allEmpty }"
      >
        <div class="energy-wrapper flex-shrink-0">
          <slot name="energy">
            <StatisticsTabs
              v-model="query.energyType"
              v-bind="tabsProps"
              :hide-trend="hideTrend"
              @click="clickTabHandler"
            />
          </slot>
        </div>
        <div class="flex-shrink-0">
          <div class="flex gap-5">
            <div
              class="charts-wrapper w-[60%] border rounded-sm"
            >
              <slot name="bar">
                <div class="padding-sm" :style="chartStyle">
                  <StatisticsBar
                    v-if="barProps.x && barProps.x.length > 0"
                    v-bind="barProps"
                  />
                  <TableEmpty v-else :image-size="120" />
                </div>
              </slot>
            </div>
            <div
              class="charts-wrapper w-[40%] border rounded-sm"
            >
              <slot name="pie">
                <div class="padding-sm" :style="chartStyle">
                  <ViewChartPie
                    v-if="!emptyPie && pieProps.source && (pieProps.source.length as number) > 0"
                    position="top"
                    radius="68%"
                    :emphasis="false"
                    :dataset="pieProps"
                    :option="{
                      legend: {
                        show: true,
                        type: 'scroll',
                        top: 3,
                      },
                      toolbox: {
                        show: true,
                        top: 30,
                        feature: {
                          dataView,
                        },
                      },
                    }"
                  />
                  <TableEmpty v-else :image-size="120 * chartHeight / 300" />
                </div>
              </slot>
            </div>
          </div>
        </div>
        <div
          class="margin-top-sm flex-direction table-wrapper flex border rounded-sm"
        >
          <slot name="table">
            <p v-if="showTips" class="fs-12 padding-right-sm text-right" style="color: var(--el-color-danger);">
              提示：明细数据与汇总数据会存在些许误差，误差由计算时小数四舍五入导致
            </p>
            <StatisticsTable
              v-if="tableProps.data && tableProps.data.length > 0"
              v-bind="tableProps"
            />
            <TableEmpty v-else :image-size="120" />
          </slot>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.statistics-main-wrapper:not(.is-all-empty) {
  @media screen and (max-width: 1630px) {
    display: block !important;
    overflow-y: auto !important;
    @include roll();
  }
}
.type-select {
  width: 100px !important;
}
.type-select :deep(.el-input) {
  min-width: auto !important;
}
.type-select :deep(.el-input__wrapper) {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
:deep(.time-picker) {
  margin-left: -1px;
}
:deep(.time-picker .el-input__wrapper) {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}
.energy-wrapper {
  min-height: 100px;
}
.charts-wrapper {
  min-height: 200px;
}
.table-wrapper {
  flex: 1;
  min-height: 100px;
  overflow: auto;
}
.table-wrapper :deep(.el-table__empty-text) {
  line-height: 20px;
}
.table-wrapper :deep(.el-table__inner-wrapper::before) {
  display: none;
}
.energy-empty {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>
